/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "EvsClient.h"
#include <common/JsonHelper.h>
#include "protect_engines/hcs/utils/HCSTokenMgr.h"
#include "protect_engines/hcs/common/HcsHttpStatus.h"

namespace {
const std::string MODULE_NAME = "EvsClient";
using Defer = std::shared_ptr<void>;
const std::string SNAPSHOT_PTRFIX_NAME = "snapshot-";  // fusionstorage 快照名称前缀
}

HCS_PLUGIN_NAMESPACE_BEGIN

bool EvsClient::CheckParams(ModelBase& model)
{
    return false;
}

// Reacquire token when token expired
    bool EvsClient::UpdateToken(ModelBase &request, std::string &tokenStr)
    {
        if (!HCSTokenMgr::GetInstance().ReacquireToken(request, tokenStr)) {
            ERRLOG("Get token failed.");
            return false;
        }
        return true;
    }

std::shared_ptr<ShowVolumeResponse> EvsClient::ShowVolumeDetail(ShowVolumeRequest &request)
{
    RequestInfo requestInfo;
    requestInfo.m_method = "GET";
    requestInfo.m_resourcePath = "{endpoint}/volumes/{volumId}";
    requestInfo.m_auth = request.GetIamUserInfo();
    std::string endpoint;
    std::string tokenStr;
    Defer _(nullptr, [&](...) { Module::CleanMemoryPwd(tokenStr); });
    if (!HCSTokenMgr::GetInstance().GetToken(request, tokenStr, endpoint)) {
        return nullptr;
    }
    requestInfo.m_pathParams["endpoint"] = endpoint;
    requestInfo.m_pathParams["projectId"] = request.GetScopeValue();
    requestInfo.m_pathParams["volumId"] = request.GetVolumeId();
    requestInfo.m_queryParams = {};
    requestInfo.m_headerParams["Content-Type"] = "application/json";
    requestInfo.m_headerParams["X-Auth-Token"] = tokenStr;
    std::shared_ptr<ShowVolumeResponse> response = std::make_shared<ShowVolumeResponse>();
    if (CallApi(requestInfo, response, request) != SUCCESS) {
        ERRLOG("EvsClient::ShowVolumeDetail CallApi failed.");
        return nullptr;
    }
    INFOLOG("Show volume detail, response body: %s", WIPE_SENSITIVE(response->GetBody()).c_str());
    if (!response->Serial()) {
        return nullptr;
    }
    return response;
}

std::shared_ptr<ShowVolumeDetailResponse> EvsClient::ShowVolumeDetailList(ShowVolumeListRequest &request)
{
    RequestInfo requestInfo;
    requestInfo.m_method = "GET";
    requestInfo.m_resourcePath = "{endpoint}/volumes/detail";
    requestInfo.m_pathParams["domain"] = request.GetEndpoint();
    requestInfo.m_pathParams["regionId"] = request.GetRegion();
    requestInfo.m_pathParams["projectId"] = request.GetScopeValue();

    requestInfo.m_auth = request.GetIamUserInfo();
    std::string endpoint;
    std::string tokenStr;
    Defer _(nullptr, [&](...) { Module::CleanMemoryPwd(tokenStr); });
    if (!HCSTokenMgr::GetInstance().GetToken(request, tokenStr, endpoint)) {
        return nullptr;
    }
    requestInfo.m_pathParams["endpoint"] = endpoint;
    requestInfo.m_headerParams["Content-Type"] = "application/json";
    requestInfo.m_headerParams["X-Auth-Token"] = tokenStr;
    if (request.GetVolumeStatusIsSet()) {
        requestInfo.m_queryParams["status"] = request.GetVolumeStatus();
    }
    if (request.GetVolumeOffsetIsSet()) {
        requestInfo.m_queryParams["offset"] = std::to_string(request.GetVolumeOffSet());
    }
    if (request.GetVolumeLimitIsSet()) {
        requestInfo.m_queryParams["limit"] = std::to_string(request.GetVolumeLimit());
    }

    std::shared_ptr<ShowVolumeDetailResponse> response = std::make_shared<ShowVolumeDetailResponse>();
    if (CallApi(requestInfo, response, request) != SUCCESS) {
        ERRLOG("Evs show volume detail list call api failed.");
        return nullptr;
    }
    INFOLOG("Show volume detail, response body: %s", WIPE_SENSITIVE(response->GetBody()).c_str());
    if (!response->Serial()) {
        ERRLOG("Get server volume detail serial failed.");
        return nullptr;
    }
    return response;
}

std::shared_ptr<OpenStackPlugin::DeleteSnapshotResponse> EvsClient::DeleteSnapshot(
    OpenStackPlugin::DeleteSnapshotRequest &request)
{
    std::string endpoint;
    std::string tokenStr;
    Defer _(nullptr, [&](...) { Module::CleanMemoryPwd(tokenStr); });
    if (!HCSTokenMgr::GetInstance().GetToken(request, tokenStr, endpoint)) {
        return nullptr;
    }
    RequestInfo reqInfo;
    reqInfo.m_method = "DELETE";
    reqInfo.m_resourcePath = "{endpoint}/snapshots/{snapshot_id}";
    reqInfo.m_pathParams["endpoint"] = endpoint;
    reqInfo.m_pathParams["snapshot_id"] = request.GetSnapshotId();
    reqInfo.m_queryParams = {};
    reqInfo.m_headerParams["X-Auth-Token"] = std::move(tokenStr);
    // fusionstorage 以快照名称标识ID snapshot-ID, 调用删除接口时需要用纯ID调用
    if (reqInfo.m_pathParams["snapshot_id"].find(SNAPSHOT_PTRFIX_NAME) != std::string::npos) {
        reqInfo.m_pathParams["snapshot_id"] = reqInfo.m_pathParams["snapshot_id"].substr(SNAPSHOT_PTRFIX_NAME.size());
    }
    INFOLOG("Common delete snapshot action.");
    std::shared_ptr<OpenStackPlugin::DeleteSnapshotResponse> response =
        std::make_shared<OpenStackPlugin::DeleteSnapshotResponse>();
    if (CallApi(reqInfo, response, request) != SUCCESS) {
        ERRLOG("Call delete snapshot API failed. Error: %s - %s",
            std::to_string(response->GetErrCode()).c_str(), response->GetErrString().c_str());
        return nullptr;
    }
    return response;
}
HCS_PLUGIN_NAMESPACE_END